/*! \file
 * \brief Enter a brief description here.
 *
 * Enter a detailed description here. (optional)
 * \author Author (Ivo Wingelaar)
 * \date Date (2011)
 * \version Version (0.0.1)
 * \copyright Copyright (GNU LGPL v3)
 */

#ifndef __LYNX_EXTENSION_HANDLER_HPP_INCLUDED__
#define __LYNX_EXTENSION_HANDLER_HPP_INCLUDED__

#include "LynxVideoManager.hpp"

#if defined(_LYNX_WINDOWS_)
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#define GL_GLEXT_LEGACY 1
#include <GL/gl.h>
#include "glext.h"
#include "wglext.h"
#else
#define GL_GLEXT_LEGACY 1
#define GLX_GLXEXT_LEGACY 1
#include <GL/gl.h>
#include <GL/glx.h>
#include <GL/glext.h>
#undef GLX_ARB_get_proc_address // avoid problems with local glxext.h
#include <GL/glxext.h>
#endif

namespace Lynx
{

static const char* const OpenGLFeatureStrings[] =
{
    "GL_3DFX_multisample",
    "GL_3DFX_tbuffer",
    "GL_3DFX_texture_compression_FXT1",
    "GL_AMD_draw_buffers_blend",
    "GL_AMD_performance_monitor",
    "GL_AMD_texture_texture4",
    "GL_AMD_vertex_shader_tesselator",
    "GL_APPLE_aux_depth_stencil",
    "GL_APPLE_client_storage",
    "GL_APPLE_element_array",
    "GL_APPLE_fence",
    "GL_APPLE_float_pixels",
    "GL_APPLE_flush_buffer_range",
    "GL_APPLE_object_purgeable",
    "GL_APPLE_rgb_422",
    "GL_APPLE_row_bytes",
    "GL_APPLE_specular_vector",
    "GL_APPLE_texture_range",
    "GL_APPLE_transform_hint",
    "GL_APPLE_vertex_array_object",
    "GL_APPLE_vertex_array_range",
    "GL_APPLE_vertex_program_evaluators",
    "GL_APPLE_ycbcr_422",
    "GL_ARB_color_buffer_float",
    "GL_ARB_compatibility",
    "GL_ARB_copy_buffer",
    "GL_ARB_depth_buffer_float",
    "GL_ARB_depth_clamp",
    "GL_ARB_depth_texture",
    "GL_ARB_draw_buffers",
    "GL_ARB_draw_buffers_blend",
    "GL_ARB_draw_elements_base_vertex",
    "GL_ARB_draw_instanced",
    "GL_ARB_fragment_coord_conventions",
    "GL_ARB_fragment_program",
    "GL_ARB_fragment_program_shadow",
    "GL_ARB_fragment_shader",
    "GL_ARB_framebuffer_object",
    "GL_ARB_framebuffer_sRGB",
    "GL_ARB_geometry_shader4",
    "GL_ARB_half_float_pixel",
    "GL_ARB_half_float_vertex",
    "GL_ARB_imaging",
    "GL_ARB_instanced_arrays",
    "GL_ARB_map_buffer_range",
    "GL_ARB_matrix_palette",
    "GL_ARB_multisample",
    "GL_ARB_multitexture",
    "GL_ARB_occlusion_query",
    "GL_ARB_pixel_buffer_object",
    "GL_ARB_point_parameters",
    "GL_ARB_point_sprite",
    "GL_ARB_provoking_vertex",
    "GL_ARB_sample_shading",
    "GL_ARB_seamless_cube_map",
    "GL_ARB_shader_objects",
    "GL_ARB_shader_texture_lod",
    "GL_ARB_shading_language_100",
    "GL_ARB_shadow",
    "GL_ARB_shadow_ambient",
    "GL_ARB_sync",
    "GL_ARB_texture_border_clamp",
    "GL_ARB_texture_buffer_object",
    "GL_ARB_texture_compression",
    "GL_ARB_texture_compression_rgtc",
    "GL_ARB_texture_cube_map",
    "GL_ARB_texture_cube_map_array",
    "GL_ARB_texture_env_add",
    "GL_ARB_texture_env_combine",
    "GL_ARB_texture_env_crossbar",
    "GL_ARB_texture_env_dot3",
    "GL_ARB_texture_float",
    "GL_ARB_texture_gather",
    "GL_ARB_texture_mirrored_repeat",
    "GL_ARB_texture_multisample",
    "GL_ARB_texture_non_power_of_two",
    "GL_ARB_texture_query_lod",
    "GL_ARB_texture_rectangle",
    "GL_ARB_texture_rg",
    "GL_ARB_transpose_matrix",
    "GL_ARB_uniform_buffer_object",
    "GL_ARB_vertex_array_bgra",
    "GL_ARB_vertex_array_object",
    "GL_ARB_vertex_blend",
    "GL_ARB_vertex_buffer_object",
    "GL_ARB_vertex_program",
    "GL_ARB_vertex_shader",
    "GL_ARB_window_pos",
    "GL_ATI_draw_buffers",
    "GL_ATI_element_array",
    "GL_ATI_envmap_bumpmap",
    "GL_ATI_fragment_shader",
    "GL_ATI_map_object_buffer",
    "GL_ATI_meminfo",
    "GL_ATI_pixel_format_float",
    "GL_ATI_pn_triangles",
    "GL_ATI_separate_stencil",
    "GL_ATI_text_fragment_shader",
    "GL_ATI_texture_env_combine3",
    "GL_ATI_texture_float",
    "GL_ATI_texture_mirror_once",
    "GL_ATI_vertex_array_object",
    "GL_ATI_vertex_attrib_array_object",
    "GL_ATI_vertex_streams",
    "GL_EXT_422_pixels",
    "GL_EXT_abgr",
    "GL_EXT_bgra",
    "GL_EXT_bindable_uniform",
    "GL_EXT_blend_color",
    "GL_EXT_blend_equation_separate",
    "GL_EXT_blend_func_separate",
    "GL_EXT_blend_logic_op",
    "GL_EXT_blend_minmax",
    "GL_EXT_blend_subtract",
    "GL_EXT_clip_volume_hint",
    "GL_EXT_cmyka",
    "GL_EXT_color_subtable",
    "GL_EXT_compiled_vertex_array",
    "GL_EXT_convolution",
    "GL_EXT_coordinate_frame",
    "GL_EXT_copy_texture",
    "GL_EXT_cull_vertex",
    "GL_EXT_depth_bounds_test",
    "GL_EXT_direct_state_access",
    "GL_EXT_draw_buffers2",
    "GL_EXT_draw_instanced",
    "GL_EXT_draw_range_elements",
    "GL_EXT_fog_coord",
    "GL_EXT_framebuffer_blit",
    "GL_EXT_framebuffer_multisample",
    "GL_EXT_framebuffer_object",
    "GL_EXT_framebuffer_sRGB",
    "GL_EXT_geometry_shader4",
    "GL_EXT_gpu_program_parameters",
    "GL_EXT_gpu_shader4",
    "GL_EXT_histogram",
    "GL_EXT_index_array_formats",
    "GL_EXT_index_func",
    "GL_EXT_index_material",
    "GL_EXT_index_texture",
    "GL_EXT_light_texture",
    "GL_EXT_misc_attribute",
    "GL_EXT_multi_draw_arrays",
    "GL_EXT_multisample",
    "GL_EXT_packed_depth_stencil",
    "GL_EXT_packed_float",
    "GL_EXT_packed_pixels",
    "GL_EXT_paletted_texture",
    "GL_EXT_pixel_buffer_object",
    "GL_EXT_pixel_transform",
    "GL_EXT_pixel_transform_color_table",
    "GL_EXT_point_parameters",
    "GL_EXT_polygon_offset",
    "GL_EXT_provoking_vertex",
    "GL_EXT_rescale_normal",
    "GL_EXT_secondary_color",
    "GL_EXT_separate_shader_objects",
    "GL_EXT_separate_specular_color",
    "GL_EXT_shadow_funcs",
    "GL_EXT_shared_texture_palette",
    "GL_EXT_stencil_clear_tag",
    "GL_EXT_stencil_two_side",
    "GL_EXT_stencil_wrap",
    "GL_EXT_subtexture",
    "GL_EXT_texture",
    "GL_EXT_texture3D",
    "GL_EXT_texture_array",
    "GL_EXT_texture_buffer_object",
    "GL_EXT_texture_compression_latc",
    "GL_EXT_texture_compression_rgtc",
    "GL_EXT_texture_compression_s3tc",
    "GL_EXT_texture_cube_map",
    "GL_EXT_texture_env_add",
    "GL_EXT_texture_env_combine",
    "GL_EXT_texture_env_dot3",
    "GL_EXT_texture_filter_anisotropic",
    "GL_EXT_texture_integer",
    "GL_EXT_texture_lod_bias",
    "GL_EXT_texture_mirror_clamp",
    "GL_EXT_texture_object",
    "GL_EXT_texture_perturb_normal",
    "GL_EXT_texture_shared_exponent",
    "GL_EXT_texture_snorm",
    "GL_EXT_texture_sRGB",
    "GL_EXT_texture_swizzle",
    "GL_EXT_timer_query",
    "GL_EXT_transform_feedback",
    "GL_EXT_vertex_array",
    "GL_EXT_vertex_array_bgra",
    "GL_EXT_vertex_shader",
    "GL_EXT_vertex_weighting",
    "GL_FfdMaskSGIX",
    "GL_GREMEDY_frame_terminator",
    "GL_GREMEDY_string_marker",
    "GL_HP_convolution_border_modes",
    "GL_HP_image_transform",
    "GL_HP_occlusion_test",
    "GL_HP_texture_lighting",
    "GL_IBM_cull_vertex",
    "GL_IBM_multimode_draw_arrays",
    "GL_IBM_rasterpos_clip",
    "GL_IBM_texture_mirrored_repeat",
    "GL_IBM_vertex_array_lists",
    "GL_INGR_blend_func_separate",
    "GL_INGR_color_clamp",
    "GL_INGR_interlace_read",
    "GL_INGR_palette_buffer",
    "GL_INTEL_parallel_arrays",
    "GL_INTEL_texture_scissor",
    "GL_MESA_pack_invert",
    "GL_MESA_resize_buffers",
    "GL_MESA_window_pos",
    "GL_MESAX_texture_stack",
    "GL_MESA_ycbcr_texture",
    "GL_NV_blend_square",
    "GL_NV_conditional_render",
    "GL_NV_copy_depth_to_color",
    "GL_NV_copy_image",
    "GL_NV_depth_buffer_float",
    "GL_NV_depth_clamp",
    "GL_NV_evaluators",
    "GL_NV_explicit_multisample",
    "GL_NV_fence",
    "GL_NV_float_buffer",
    "GL_NV_fog_distance",
    "GL_NV_fragment_program",
    "GL_NV_fragment_program2",
    "GL_NV_fragment_program4",
    "GL_NV_fragment_program_option",
    "GL_NV_framebuffer_multisample_coverage",
    "GL_NV_geometry_program4",
    "GL_NV_geometry_shader4",
    "GL_NV_gpu_program4",
    "GL_NV_half_float",
    "GL_NV_light_max_exponent",
    "GL_NV_multisample_filter_hint",
    "GL_NV_occlusion_query",
    "GL_NV_packed_depth_stencil",
    "GL_NV_parameter_buffer_object",
    "GL_NV_parameter_buffer_object2",
    "GL_NV_pixel_data_range",
    "GL_NV_point_sprite",
    "GL_NV_present_video",
    "GL_NV_primitive_restart",
    "GL_NV_register_combiners",
    "GL_NV_register_combiners2",
    "GL_NV_shader_buffer_load",
    "GL_NV_texgen_emboss",
    "GL_NV_texgen_reflection",
    "GL_NV_texture_barrier",
    "GL_NV_texture_compression_vtc",
    "GL_NV_texture_env_combine4",
    "GL_NV_texture_expand_normal",
    "GL_NV_texture_rectangle",
    "GL_NV_texture_shader",
    "GL_NV_texture_shader2",
    "GL_NV_texture_shader3",
    "GL_NV_transform_feedback",
    "GL_NV_transform_feedback2",
    "GL_NV_vertex_array_range",
    "GL_NV_vertex_array_range2",
    "GL_NV_vertex_buffer_unified_memory",
    "GL_NV_vertex_program",
    "GL_NV_vertex_program1_1",
    "GL_NV_vertex_program2",
    "GL_NV_vertex_program2_option",
    "GL_NV_vertex_program3",
    "GL_NV_vertex_program4",
    "GL_NV_video_capture",
    "GL_OES_read_format",
    "GL_OML_interlace",
    "GL_OML_resample",
    "GL_OML_subsample",
    "GL_PGI_misc_hints",
    "GL_PGI_vertex_hints",
    "GL_REND_screen_coordinates",
    "GL_S3_s3tc",
    "GL_SGI_color_matrix",
    "GL_SGI_color_table",
    "GL_SGI_depth_pass_instrument",
    "GL_SGIS_detail_texture",
    "GL_SGIS_fog_function",
    "GL_SGIS_generate_mipmap",
    "GL_SGIS_multisample",
    "GL_SGIS_pixel_texture",
    "GL_SGIS_point_line_texgen",
    "GL_SGIS_point_parameters",
    "GL_SGIS_sharpen_texture",
    "GL_SGIS_texture4D",
    "GL_SGIS_texture_border_clamp",
    "GL_SGIS_texture_color_mask",
    "GL_SGIS_texture_edge_clamp",
    "GL_SGIS_texture_filter4",
    "GL_SGIS_texture_lod",
    "GL_SGIS_texture_select",
    "GL_SGI_texture_color_table",
    "GL_SGIX_async",
    "GL_SGIX_async_histogram",
    "GL_SGIX_async_pixel",
    "GL_SGIX_blend_alpha_minmax",
    "GL_SGIX_calligraphic_fragment",
    "GL_SGIX_clipmap",
    "GL_SGIX_convolution_accuracy",
    "GL_SGIX_depth_pass_instrument",
    "GL_SGIX_depth_texture",
    "GL_SGIX_flush_raster",
    "GL_SGIX_fog_offset",
    "GL_SGIX_fog_scale",
    "GL_SGIX_fragment_lighting",
    "GL_SGIX_framezoom",
    "GL_SGIX_igloo_interface",
    "GL_SGIX_impact_pixel_texture",
    "GL_SGIX_instruments",
    "GL_SGIX_interlace",
    "GL_SGIX_ir_instrument1",
    "GL_SGIX_list_priority",
    "GL_SGIX_pixel_texture",
    "GL_SGIX_pixel_tiles",
    "GL_SGIX_polynomial_ffd",
    "GL_SGIX_reference_plane",
    "GL_SGIX_resample",
    "GL_SGIX_scalebias_hint",
    "GL_SGIX_shadow",
    "GL_SGIX_shadow_ambient",
    "GL_SGIX_sprite",
    "GL_SGIX_subsample",
    "GL_SGIX_tag_sample_buffer",
    "GL_SGIX_texture_add_env",
    "GL_SGIX_texture_coordinate_clamp",
    "GL_SGIX_texture_lod_bias",
    "GL_SGIX_texture_multi_buffer",
    "GL_SGIX_texture_scale_bias",
    "GL_SGIX_texture_select",
    "GL_SGIX_vertex_preclip",
    "GL_SGIX_ycrcb",
    "GL_SGIX_ycrcba",
    "GL_SGIX_ycrcb_subsample",
    "GL_SUN_convolution_border_modes",
    "GL_SUN_global_alpha",
    "GL_SUN_mesh_array",
    "GL_SUN_slice_accum",
    "GL_SUN_triangle_list",
    "GL_SUN_vertex",
    "GL_SUNX_constant_data",
    "GL_WIN_phong_shading",
    "GL_WIN_specular_fog"
};

class OpenGLExtensionHandler
{
public:
    enum EOpenGLFeatures
    {
        LYNX_3DFX_multisample = 0,
        LYNX_3DFX_tbuffer,
        LYNX_3DFX_texture_compression_FXT1,
        LYNX_AMD_draw_buffers_blend,
        LYNX_AMD_performance_monitor,
        LYNX_AMD_texture_texture4,
        LYNX_AMD_vertex_shader_tesselator,
        LYNX_APPLE_aux_depth_stencil,
        LYNX_APPLE_client_storage,
        LYNX_APPLE_element_array,
        LYNX_APPLE_fence,
        LYNX_APPLE_float_pixels,
        LYNX_APPLE_flush_buffer_range,
        LYNX_APPLE_object_purgeable,
        LYNX_APPLE_rgb_422,
        LYNX_APPLE_row_bytes,
        LYNX_APPLE_specular_vector,
        LYNX_APPLE_texture_range,
        LYNX_APPLE_transform_hint,
        LYNX_APPLE_vertex_array_object,
        LYNX_APPLE_vertex_array_range,
        LYNX_APPLE_vertex_program_evaluators,
        LYNX_APPLE_ycbcr_422,
        LYNX_ARB_color_buffer_float,
        LYNX_ARB_compatibility,
        LYNX_ARB_copy_buffer,
        LYNX_ARB_depth_buffer_float,
        LYNX_ARB_depth_clamp,
        LYNX_ARB_depth_texture,
        LYNX_ARB_draw_buffers,
        LYNX_ARB_draw_buffers_blend,
        LYNX_ARB_draw_elements_base_vertex,
        LYNX_ARB_draw_instanced,
        LYNX_ARB_fragment_coord_conventions,
        LYNX_ARB_fragment_program,
        LYNX_ARB_fragment_program_shadow,
        LYNX_ARB_fragment_shader,
        LYNX_ARB_framebuffer_object,
        LYNX_ARB_framebuffer_sRGB,
        LYNX_ARB_geometry_shader4,
        LYNX_ARB_half_float_pixel,
        LYNX_ARB_half_float_vertex,
        LYNX_ARB_imaging,
        LYNX_ARB_instanced_arrays,
        LYNX_ARB_map_buffer_range,
        LYNX_ARB_matrix_palette,
        LYNX_ARB_multisample,
        LYNX_ARB_multitexture,
        LYNX_ARB_occlusion_query,
        LYNX_ARB_pixel_buffer_object,
        LYNX_ARB_point_parameters,
        LYNX_ARB_point_sprite,
        LYNX_ARB_provoking_vertex,
        LYNX_ARB_sample_shading,
        LYNX_ARB_seamless_cube_map,
        LYNX_ARB_shader_objects,
        LYNX_ARB_shader_texture_lod,
        LYNX_ARB_shading_language_100,
        LYNX_ARB_shadow,
        LYNX_ARB_shadow_ambient,
        LYNX_ARB_sync,
        LYNX_ARB_texture_border_clamp,
        LYNX_ARB_texture_buffer_object,
        LYNX_ARB_texture_compression,
        LYNX_ARB_texture_compression_rgtc,
        LYNX_ARB_texture_cube_map,
        LYNX_ARB_texture_cube_map_array,
        LYNX_ARB_texture_env_add,
        LYNX_ARB_texture_env_combine,
        LYNX_ARB_texture_env_crossbar,
        LYNX_ARB_texture_env_dot3,
        LYNX_ARB_texture_float,
        LYNX_ARB_texture_gather,
        LYNX_ARB_texture_mirrored_repeat,
        LYNX_ARB_texture_multisample,
        LYNX_ARB_texture_non_power_of_two,
        LYNX_ARB_texture_query_lod,
        LYNX_ARB_texture_rectangle,
        LYNX_ARB_texture_rg,
        LYNX_ARB_transpose_matrix,
        LYNX_ARB_uniform_buffer_object,
        LYNX_ARB_vertex_array_bgra,
        LYNX_ARB_vertex_array_object,
        LYNX_ARB_vertex_blend,
        LYNX_ARB_vertex_buffer_object,
        LYNX_ARB_vertex_program,
        LYNX_ARB_vertex_shader,
        LYNX_ARB_window_pos,
        LYNX_ATI_draw_buffers,
        LYNX_ATI_element_array,
        LYNX_ATI_envmap_bumpmap,
        LYNX_ATI_fragment_shader,
        LYNX_ATI_map_object_buffer,
        LYNX_ATI_meminfo,
        LYNX_ATI_pixel_format_float,
        LYNX_ATI_pn_triangles,
        LYNX_ATI_separate_stencil,
        LYNX_ATI_text_fragment_shader,
        LYNX_ATI_texture_env_combine3,
        LYNX_ATI_texture_float,
        LYNX_ATI_texture_mirror_once,
        LYNX_ATI_vertex_array_object,
        LYNX_ATI_vertex_attrib_array_object,
        LYNX_ATI_vertex_streams,
        LYNX_EXT_422_pixels,
        LYNX_EXT_abgr,
        LYNX_EXT_bgra,
        LYNX_EXT_bindable_uniform,
        LYNX_EXT_blend_color,
        LYNX_EXT_blend_equation_separate,
        LYNX_EXT_blend_func_separate,
        LYNX_EXT_blend_logic_op,
        LYNX_EXT_blend_minmax,
        LYNX_EXT_blend_subtract,
        LYNX_EXT_clip_volume_hint,
        LYNX_EXT_cmyka,
        LYNX_EXT_color_subtable,
        LYNX_EXT_compiled_vertex_array,
        LYNX_EXT_convolution,
        LYNX_EXT_coordinate_frame,
        LYNX_EXT_copy_texture,
        LYNX_EXT_cull_vertex,
        LYNX_EXT_depth_bounds_test,
        LYNX_EXT_direct_state_access,
        LYNX_EXT_draw_buffers2,
        LYNX_EXT_draw_instanced,
        LYNX_EXT_draw_range_elements,
        LYNX_EXT_fog_coord,
        LYNX_EXT_framebuffer_blit,
        LYNX_EXT_framebuffer_multisample,
        LYNX_EXT_framebuffer_object,
        LYNX_EXT_framebuffer_sRGB,
        LYNX_EXT_geometry_shader4,
        LYNX_EXT_gpu_program_parameters,
        LYNX_EXT_gpu_shader4,
        LYNX_EXT_histogram,
        LYNX_EXT_index_array_formats,
        LYNX_EXT_index_func,
        LYNX_EXT_index_material,
        LYNX_EXT_index_texture,
        LYNX_EXT_light_texture,
        LYNX_EXT_misc_attribute,
        LYNX_EXT_multi_draw_arrays,
        LYNX_EXT_multisample,
        LYNX_EXT_packed_depth_stencil,
        LYNX_EXT_packed_float,
        LYNX_EXT_packed_pixels,
        LYNX_EXT_paletted_texture,
        LYNX_EXT_pixel_buffer_object,
        LYNX_EXT_pixel_transform,
        LYNX_EXT_pixel_transform_color_table,
        LYNX_EXT_point_parameters,
        LYNX_EXT_polygon_offset,
        LYNX_EXT_provoking_vertex,
        LYNX_EXT_rescale_normal,
        LYNX_EXT_secondary_color,
        LYNX_EXT_separate_shader_objects,
        LYNX_EXT_separate_specular_color,
        LYNX_EXT_shadow_funcs,
        LYNX_EXT_shared_texture_palette,
        LYNX_EXT_stencil_clear_tag,
        LYNX_EXT_stencil_two_side,
        LYNX_EXT_stencil_wrap,
        LYNX_EXT_subtexture,
        LYNX_EXT_texture,
        LYNX_EXT_texture3D,
        LYNX_EXT_texture_array,
        LYNX_EXT_texture_buffer_object,
        LYNX_EXT_texture_compression_latc,
        LYNX_EXT_texture_compression_rgtc,
        LYNX_EXT_texture_compression_s3tc,
        LYNX_EXT_texture_cube_map,
        LYNX_EXT_texture_env_add,
        LYNX_EXT_texture_env_combine,
        LYNX_EXT_texture_env_dot3,
        LYNX_EXT_texture_filter_anisotropic,
        LYNX_EXT_texture_integer,
        LYNX_EXT_texture_lod_bias,
        LYNX_EXT_texture_mirror_clamp,
        LYNX_EXT_texture_object,
        LYNX_EXT_texture_perturb_normal,
        LYNX_EXT_texture_shared_exponent,
        LYNX_EXT_texture_snorm,
        LYNX_EXT_texture_sRGB,
        LYNX_EXT_texture_swizzle,
        LYNX_EXT_timer_query,
        LYNX_EXT_transform_feedback,
        LYNX_EXT_vertex_array,
        LYNX_EXT_vertex_array_bgra,
        LYNX_EXT_vertex_shader,
        LYNX_EXT_vertex_weighting,
        LYNX_FfdMaskSGIX,
        LYNX_GREMEDY_frame_terminator,
        LYNX_GREMEDY_string_marker,
        LYNX_HP_convolution_border_modes,
        LYNX_HP_image_transform,
        LYNX_HP_occlusion_test,
        LYNX_HP_texture_lighting,
        LYNX_IBM_cull_vertex,
        LYNX_IBM_multimode_draw_arrays,
        LYNX_IBM_rasterpos_clip,
        LYNX_IBM_texture_mirrored_repeat,
        LYNX_IBM_vertex_array_lists,
        LYNX_INGR_blend_func_separate,
        LYNX_INGR_color_clamp,
        LYNX_INGR_interlace_read,
        LYNX_INGR_palette_buffer,
        LYNX_INTEL_parallel_arrays,
        LYNX_INTEL_texture_scissor,
        LYNX_MESA_pack_invert,
        LYNX_MESA_resize_buffers,
        LYNX_MESA_window_pos,
        LYNX_MESAX_texture_stack,
        LYNX_MESA_ycbcr_texture,
        LYNX_NV_blend_square,
        LYNX_NV_conditional_render,
        LYNX_NV_copy_depth_to_color,
        LYNX_NV_copy_image,
        LYNX_NV_depth_buffer_float,
        LYNX_NV_depth_clamp,
        LYNX_NV_evaluators,
        LYNX_NV_explicit_multisample,
        LYNX_NV_fence,
        LYNX_NV_float_buffer,
        LYNX_NV_fog_distance,
        LYNX_NV_fragment_program,
        LYNX_NV_fragment_program2,
        LYNX_NV_fragment_program4,
        LYNX_NV_fragment_program_option,
        LYNX_NV_framebuffer_multisample_coverage,
        LYNX_NV_geometry_program4,
        LYNX_NV_geometry_shader4,
        LYNX_NV_gpu_program4,
        LYNX_NV_half_float,
        LYNX_NV_light_max_exponent,
        LYNX_NV_multisample_filter_hint,
        LYNX_NV_occlusion_query,
        LYNX_NV_packed_depth_stencil,
        LYNX_NV_parameter_buffer_object,
        LYNX_NV_parameter_buffer_object2,
        LYNX_NV_pixel_data_range,
        LYNX_NV_point_sprite,
        LYNX_NV_present_video,
        LYNX_NV_primitive_restart,
        LYNX_NV_register_combiners,
        LYNX_NV_register_combiners2,
        LYNX_NV_shader_buffer_load,
        LYNX_NV_texgen_emboss,
        LYNX_NV_texgen_reflection,
        LYNX_NV_texture_barrier,
        LYNX_NV_texture_compression_vtc,
        LYNX_NV_texture_env_combine4,
        LYNX_NV_texture_expand_normal,
        LYNX_NV_texture_rectangle,
        LYNX_NV_texture_shader,
        LYNX_NV_texture_shader2,
        LYNX_NV_texture_shader3,
        LYNX_NV_transform_feedback,
        LYNX_NV_transform_feedback2,
        LYNX_NV_vertex_array_range,
        LYNX_NV_vertex_array_range2,
        LYNX_NV_vertex_buffer_unified_memory,
        LYNX_NV_vertex_program,
        LYNX_NV_vertex_program1_1,
        LYNX_NV_vertex_program2,
        LYNX_NV_vertex_program2_option,
        LYNX_NV_vertex_program3,
        LYNX_NV_vertex_program4,
        LYNX_NV_video_capture,
        LYNX_OES_read_format,
        LYNX_OML_interlace,
        LYNX_OML_resample,
        LYNX_OML_subsample,
        LYNX_PGI_misc_hints,
        LYNX_PGI_vertex_hints,
        LYNX_REND_screen_coordinates,
        LYNX_S3_s3tc,
        LYNX_SGI_color_matrix,
        LYNX_SGI_color_table,
        LYNX_SGI_depth_pass_instrument,
        LYNX_SGIS_detail_texture,
        LYNX_SGIS_fog_function,
        LYNX_SGIS_generate_mipmap,
        LYNX_SGIS_multisample,
        LYNX_SGIS_pixel_texture,
        LYNX_SGIS_point_line_texgen,
        LYNX_SGIS_point_parameters,
        LYNX_SGIS_sharpen_texture,
        LYNX_SGIS_texture4D,
        LYNX_SGIS_texture_border_clamp,
        LYNX_SGIS_texture_color_mask,
        LYNX_SGIS_texture_edge_clamp,
        LYNX_SGIS_texture_filter4,
        LYNX_SGIS_texture_lod,
        LYNX_SGIS_texture_select,
        LYNX_SGI_texture_color_table,
        LYNX_SGIX_async,
        LYNX_SGIX_async_histogram,
        LYNX_SGIX_async_pixel,
        LYNX_SGIX_blend_alpha_minmax,
        LYNX_SGIX_calligraphic_fragment,
        LYNX_SGIX_clipmap,
        LYNX_SGIX_convolution_accuracy,
        LYNX_SGIX_depth_pass_instrument,
        LYNX_SGIX_depth_texture,
        LYNX_SGIX_flush_raster,
        LYNX_SGIX_fog_offset,
        LYNX_SGIX_fog_scale,
        LYNX_SGIX_fragment_lighting,
        LYNX_SGIX_framezoom,
        LYNX_SGIX_igloo_interface,
        LYNX_SGIX_impact_pixel_texture,
        LYNX_SGIX_instruments,
        LYNX_SGIX_interlace,
        LYNX_SGIX_ir_instrument1,
        LYNX_SGIX_list_priority,
        LYNX_SGIX_pixel_texture,
        LYNX_SGIX_pixel_tiles,
        LYNX_SGIX_polynomial_ffd,
        LYNX_SGIX_reference_plane,
        LYNX_SGIX_resample,
        LYNX_SGIX_scalebias_hint,
        LYNX_SGIX_shadow,
        LYNX_SGIX_shadow_ambient,
        LYNX_SGIX_sprite,
        LYNX_SGIX_subsample,
        LYNX_SGIX_tag_sample_buffer,
        LYNX_SGIX_texture_add_env,
        LYNX_SGIX_texture_coordinate_clamp,
        LYNX_SGIX_texture_lod_bias,
        LYNX_SGIX_texture_multi_buffer,
        LYNX_SGIX_texture_scale_bias,
        LYNX_SGIX_texture_select,
        LYNX_SGIX_vertex_preclip,
        LYNX_SGIX_ycrcb,
        LYNX_SGIX_ycrcba,
        LYNX_SGIX_ycrcb_subsample,
        LYNX_SUN_convolution_border_modes,
        LYNX_SUN_global_alpha,
        LYNX_SUN_mesh_array,
        LYNX_SUN_slice_accum,
        LYNX_SUN_triangle_list,
        LYNX_SUN_vertex,
        LYNX_SUNX_constant_data,
        LYNX_WIN_phong_shading,
        LYNX_WIN_specular_fog,
        LYNX_OpenGL_Feature_Count
    };

    // constructor
    OpenGLExtensionHandler(LogManager* logger);

    // deferred initialization
    void initExtensions(bool stencilBuffer);

    //! queries the features of the driver, returns true if feature is available
    bool query_feature(E_VIDEO_MANAGER_FEATURE feature) const;

    //! queries the features of the driver, returns true if feature is available
    bool queryOpenGLFeature(EOpenGLFeatures feature) const
    {
        return mFeatureAvailable[feature];
    }

    //! show all features with availablity
    void dump() const;

    // Some variables for properties
    bool mStencilBuffer;
    bool mMultiTextureExtension;
    bool mTextureCompressionExtension;

    // Some non-boolean properties
    //! Maxmimum texture layers supported by the fixed pipeline
    uint8_t mMaxTextureUnits;
    //! Maximum hardware lights supported
    uint8_t mMaxLights;
    //! Maximal Anisotropy
    uint8_t mMaxAnisotropy;
    //! Number of user clipplanes
    uint8_t mMaxUserClipPlanes;
    //! Number of auxiliary buffers
    uint8_t mMaxAuxBuffers;
    //! Number of rendertargets available as MRTs
    uint8_t mMaxMultipleRenderTargets;
    //! Optimal number of indices per meshbuffer
    uint32_t mMaxIndices;
    //! Maximal texture dimension
    uint32_t mMaxTextureSize;
    //! Maximal vertices handled by geometry shaders
    uint32_t mMaxGeometryVerticesOut;
    //! Maximal LOD Bias
    float mMaxTextureLODBias;
    //! Minimal and maximal supported thickness for lines without smoothing
    GLfloat mDimAliasedLine[2];
    //! Minimal and maximal supported thickness for points without smoothing
    GLfloat mDimAliasedPoint[2];
    //! Minimal and maximal supported thickness for lines with smoothing
    GLfloat mDimSmoothedLine[2];
    //! Minimal and maximal supported thickness for points with smoothing
    GLfloat mDimSmoothedPoint[2];

    //! OpenGL version as Integer: 100*Major+Minor, i.e. 2.1 becomes 201
    uint16_t mVersion;
    //! GLSL version as Integer: 100*Major+Minor
    uint16_t mShaderLanguageVersion;

    // public access to the (loaded) extensions.
    // general functions
    void extGlActiveTexture(GLenum texture);
    void extGlClientActiveTexture(GLenum texture);
    void extGlPointParameterf(GLint loc, GLfloat f);
    void extGlPointParameterfv(GLint loc, const GLfloat* v);
    void extGlStencilFuncSeparate(GLenum frontfunc, GLenum backfunc, GLint ref, GLuint mask);
    void extGlStencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass);
    void extGlCompressedTexImage2D(GLenum target, GLint level,
                                   GLenum internalformat, GLsizei width, GLsizei height,
                                   GLint border, GLsizei imageSize, const void* data);

    // shader programming
    void extGlGenPrograms(GLsizei n, GLuint* programs);
    void extGlBindProgram(GLenum target, GLuint program);
    void extGlProgramString(GLenum target, GLenum format, GLsizei len, const GLvoid* string);
    void extGlLoadProgram(GLenum target, GLuint id, GLsizei len, const GLubyte* string);
    void extGlDeletePrograms(GLsizei n, const GLuint* programs);
    void extGlProgramLocalParameter4fv(GLenum, GLuint, const GLfloat *);
    GLhandleARB extGlCreateShaderObject(GLenum shaderType);
    // note: Due to the type confusion between shader_objects and OpenGL 2.0
    // we have to add the ARB extension for proper method definitions in case
    // that handleARB and uint are the same type
    void extGlShaderSourceARB(GLhandleARB shader, int numOfStrings, const char** strings, int* lenOfStrings);
    void extGlCompileShaderARB(GLhandleARB shader);
    GLhandleARB extGlCreateProgramObject(void);
    void extGlAttachObject(GLhandleARB program, GLhandleARB shader);
    void extGlLinkProgramARB(GLhandleARB program);
    void extGlUseProgramObject(GLhandleARB prog);
    void extGlDeleteObject(GLhandleARB object);
    void extGlGetAttachedObjects(GLhandleARB program, GLsizei maxcount, GLsizei* count, GLhandleARB* shaders);
    void extGlGetInfoLog(GLhandleARB object, GLsizei maxLength, GLsizei* length, GLcharARB* infoLog);
    void extGlGetObjectParameteriv(GLhandleARB object, GLenum type, GLint* param);
    GLint extGlGetUniformLocationARB(GLhandleARB program, const char* name);
    void extGlUniform4fv(GLint location, GLsizei count, const GLfloat* v);
    void extGlUniform1iv(GLint loc, GLsizei count, const GLint* v);
    void extGlUniform1fv(GLint loc, GLsizei count, const GLfloat* v);
    void extGlUniform2fv(GLint loc, GLsizei count, const GLfloat* v);
    void extGlUniform3fv(GLint loc, GLsizei count, const GLfloat* v);
    void extGlUniformMatrix2fv(GLint loc, GLsizei count, GLboolean transpose, const GLfloat* v);
    void extGlUniformMatrix3fv(GLint loc, GLsizei count, GLboolean transpose, const GLfloat* v);
    void extGlUniformMatrix4fv(GLint loc, GLsizei count, GLboolean transpose, const GLfloat* v);
    void extGlGetActiveUniformARB(GLhandleARB program, GLuint index, GLsizei maxlength, GLsizei* length, GLint* size, GLenum* type, GLcharARB* name);

    // framebuffer objects
    void extGlBindFramebuffer(GLenum target, GLuint framebuffer);
    void extGlDeleteFramebuffers(GLsizei n, const GLuint* framebuffers);
    void extGlGenFramebuffers(GLsizei n, GLuint* framebuffers);
    GLenum extGlCheckFramebufferStatus(GLenum target);
    void extGlFramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
    void extGlBindRenderbuffer(GLenum target, GLuint renderbuffer);
    void extGlDeleteRenderbuffers(GLsizei n, const GLuint* renderbuffers);
    void extGlGenRenderbuffers(GLsizei n, GLuint* renderbuffers);
    void extGlRenderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
    void extGlFramebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
    void extGlActiveStencilFace(GLenum face);
    void extGlDrawBuffers(GLsizei n, const GLenum* bufs);

    // vertex buffer object
    void extGlGenBuffers(GLsizei n, GLuint* buffers);
    void extGlBindBuffer(GLenum target, GLuint buffer);
    void extGlBufferData(GLenum target, GLsizeiptrARB size, const GLvoid* data, GLenum usage);
    void extGlDeleteBuffers(GLsizei n, const GLuint* buffers);
    void extGlBufferSubData(GLenum target, GLintptrARB offset, GLsizeiptrARB size, const GLvoid* data);
    void extGlGetBufferSubData(GLenum target, GLintptrARB offset, GLsizeiptrARB size, GLvoid* data);
    void* extGlMapBuffer(GLenum target, GLenum access);
    GLboolean extGlUnmapBuffer(GLenum target);
    GLboolean extGlIsBuffer(GLuint buffer);
    void extGlGetBufferParameteriv(GLenum target, GLenum pname, GLint* params);
    void extGlGetBufferPointerv(GLenum target, GLenum pname, GLvoid** params);
    void extGlProvokingVertex(GLenum mode);
    void extGlColorMaskIndexed(GLuint buf, GLboolean r, GLboolean g, GLboolean b, GLboolean a);
    void extGlEnableIndexed(GLenum target, GLuint index);
    void extGlDisableIndexed(GLenum target, GLuint index);
    void extGlBlendFuncIndexed(GLuint buf, GLenum src, GLenum dst);
    void extGlProgramParameteri(GLuint program, GLenum pname, GLint value);


protected:
    // the global feature array
    bool mFeatureAvailable[LYNX_OpenGL_Feature_Count];

    LogManager* mLogManager;

    PFNGLACTIVETEXTUREARBPROC pGlActiveTextureARB;
    PFNGLCLIENTACTIVETEXTUREARBPROC	pGlClientActiveTextureARB;
    PFNGLGENPROGRAMSARBPROC pGlGenProgramsARB;
    PFNGLGENPROGRAMSNVPROC pGlGenProgramsNV;
    PFNGLBINDPROGRAMARBPROC pGlBindProgramARB;
    PFNGLBINDPROGRAMNVPROC pGlBindProgramNV;
    PFNGLDELETEPROGRAMSARBPROC pGlDeleteProgramsARB;
    PFNGLDELETEPROGRAMSNVPROC pGlDeleteProgramsNV;
    PFNGLPROGRAMSTRINGARBPROC pGlProgramStringARB;
    PFNGLLOADPROGRAMNVPROC pGlLoadProgramNV;
    PFNGLPROGRAMLOCALPARAMETER4FVARBPROC pGlProgramLocalParameter4fvARB;
    PFNGLCREATESHADEROBJECTARBPROC pGlCreateShaderObjectARB;
    PFNGLSHADERSOURCEARBPROC pGlShaderSourceARB;
    PFNGLCOMPILESHADERARBPROC pGlCompileShaderARB;
    PFNGLCREATEPROGRAMOBJECTARBPROC pGlCreateProgramObjectARB;
    PFNGLATTACHOBJECTARBPROC pGlAttachObjectARB;
    PFNGLLINKPROGRAMARBPROC pGlLinkProgramARB;
    PFNGLUSEPROGRAMOBJECTARBPROC pGlUseProgramObjectARB;
    PFNGLDELETEOBJECTARBPROC pGlDeleteObjectARB;
    PFNGLGETATTACHEDOBJECTSARBPROC pGlGetAttachedObjectsARB;
    PFNGLGETINFOLOGARBPROC pGlGetInfoLogARB;
    PFNGLGETOBJECTPARAMETERIVARBPROC pGlGetObjectParameterivARB;
    PFNGLGETUNIFORMLOCATIONARBPROC pGlGetUniformLocationARB;
    PFNGLUNIFORM1IVARBPROC pGlUniform1ivARB;
    PFNGLUNIFORM1FVARBPROC pGlUniform1fvARB;
    PFNGLUNIFORM2FVARBPROC pGlUniform2fvARB;
    PFNGLUNIFORM3FVARBPROC pGlUniform3fvARB;
    PFNGLUNIFORM4FVARBPROC pGlUniform4fvARB;
    PFNGLUNIFORMMATRIX2FVARBPROC pGlUniformMatrix2fvARB;
    PFNGLUNIFORMMATRIX3FVARBPROC pGlUniformMatrix3fvARB;
    PFNGLUNIFORMMATRIX4FVARBPROC pGlUniformMatrix4fvARB;
    PFNGLGETACTIVEUNIFORMARBPROC pGlGetActiveUniformARB;
    PFNGLPOINTPARAMETERFARBPROC  pGlPointParameterfARB;
    PFNGLPOINTPARAMETERFVARBPROC pGlPointParameterfvARB;
    PFNGLSTENCILFUNCSEPARATEPROC pGlStencilFuncSeparate;
    PFNGLSTENCILOPSEPARATEPROC pGlStencilOpSeparate;
    PFNGLSTENCILFUNCSEPARATEATIPROC pGlStencilFuncSeparateATI;
    PFNGLSTENCILOPSEPARATEATIPROC pGlStencilOpSeparateATI;
    PFNGLCOMPRESSEDTEXIMAGE2DPROC pGlCompressedTexImage2D;
#if defined(_LYNX_LINUX_) && defined(GLX_SGI_swap_control)
    PFNGLXSWAPINTERVALSGIPROC glxSwapIntervalSGI;
#endif
#if defined(_LYNX_LINUX_) && defined(GLX_EXT_swap_control)
    PFNGLXSWAPINTERVALEXTPROC glxSwapIntervalEXT;
#endif
    PFNGLBINDFRAMEBUFFEREXTPROC pGlBindFramebufferEXT;
    PFNGLDELETEFRAMEBUFFERSEXTPROC pGlDeleteFramebuffersEXT;
    PFNGLGENFRAMEBUFFERSEXTPROC pGlGenFramebuffersEXT;
    PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC pGlCheckFramebufferStatusEXT;
    PFNGLFRAMEBUFFERTEXTURE2DEXTPROC pGlFramebufferTexture2DEXT;
    PFNGLBINDRENDERBUFFEREXTPROC pGlBindRenderbufferEXT;
    PFNGLDELETERENDERBUFFERSEXTPROC pGlDeleteRenderbuffersEXT;
    PFNGLGENRENDERBUFFERSEXTPROC pGlGenRenderbuffersEXT;
    PFNGLRENDERBUFFERSTORAGEEXTPROC pGlRenderbufferStorageEXT;
    PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC pGlFramebufferRenderbufferEXT;
    PFNGLACTIVESTENCILFACEEXTPROC pGlActiveStencilFaceEXT;
    PFNGLDRAWBUFFERSARBPROC pGlDrawBuffersARB;
    PFNGLDRAWBUFFERSATIPROC pGlDrawBuffersATI;
    PFNGLGENBUFFERSARBPROC pGlGenBuffersARB;
    PFNGLBINDBUFFERARBPROC pGlBindBufferARB;
    PFNGLBUFFERDATAARBPROC pGlBufferDataARB;
    PFNGLDELETEBUFFERSARBPROC pGlDeleteBuffersARB;
    PFNGLBUFFERSUBDATAARBPROC pGlBufferSubDataARB;
    PFNGLGETBUFFERSUBDATAARBPROC pGlGetBufferSubDataARB;
    PFNGLMAPBUFFERARBPROC pGlMapBufferARB;
    PFNGLUNMAPBUFFERARBPROC pGlUnmapBufferARB;
    PFNGLISBUFFERARBPROC pGlIsBufferARB;
    PFNGLGETBUFFERPARAMETERIVARBPROC pGlGetBufferParameterivARB;
    PFNGLGETBUFFERPOINTERVARBPROC pGlGetBufferPointervARB;
    PFNGLPROVOKINGVERTEXPROC pGlProvokingVertexARB;
    PFNGLPROVOKINGVERTEXEXTPROC pGlProvokingVertexEXT;
    PFNGLCOLORMASKINDEXEDEXTPROC pGlColorMaskIndexedEXT;
    PFNGLENABLEINDEXEDEXTPROC pGlEnableIndexedEXT;
    PFNGLDISABLEINDEXEDEXTPROC pGlDisableIndexedEXT;
    PFNGLBLENDFUNCINDEXEDAMDPROC pGlBlendFuncIndexedAMD;
    PFNGLBLENDFUNCIPROC pGlBlendFunciARB;
    PFNGLPROGRAMPARAMETERIARBPROC pGlProgramParameteriARB;
    PFNGLPROGRAMPARAMETERIEXTPROC pGlProgramParameteriEXT;
};

inline void OpenGLExtensionHandler::extGlActiveTexture(GLenum texture)
{
    if(mMultiTextureExtension && pGlActiveTextureARB)
        pGlActiveTextureARB(texture);
}

inline void OpenGLExtensionHandler::extGlClientActiveTexture(GLenum texture)
{
    if(mMultiTextureExtension && pGlClientActiveTextureARB)
        pGlClientActiveTextureARB(texture);
}

inline void OpenGLExtensionHandler::extGlGenPrograms(GLsizei n, GLuint* programs)
{
    if(pGlGenProgramsARB)
        pGlGenProgramsARB(n, programs);
    else if(pGlGenProgramsNV)
        pGlGenProgramsNV(n, programs);
}

inline void OpenGLExtensionHandler::extGlBindProgram(GLenum target, GLuint program)
{
    if(pGlBindProgramARB)
        pGlBindProgramARB(target, program);
    else if(pGlBindProgramNV)
        pGlBindProgramNV(target, program);
}

inline void OpenGLExtensionHandler::extGlProgramString(GLenum target, GLenum format, GLsizei len, const GLvoid* string)
{
    if(pGlProgramStringARB)
        pGlProgramStringARB(target, format, len, string);
}

inline void OpenGLExtensionHandler::extGlLoadProgram(GLenum target, GLuint id, GLsizei len, const GLubyte* string)
{
    if(pGlLoadProgramNV)
        pGlLoadProgramNV(target, id, len, string);
}

inline void OpenGLExtensionHandler::extGlDeletePrograms(GLsizei n, const GLuint* programs)
{
    if(pGlDeleteProgramsARB)
        pGlDeleteProgramsARB(n, programs);
    else if(pGlDeleteProgramsNV)
        pGlDeleteProgramsNV(n, programs);
}

inline void OpenGLExtensionHandler::extGlProgramLocalParameter4fv(GLenum n, GLuint i, const GLfloat* f)
{
    if(pGlProgramLocalParameter4fvARB)
        pGlProgramLocalParameter4fvARB(n,i,f);
}

inline GLhandleARB OpenGLExtensionHandler::extGlCreateShaderObject(GLenum shaderType)
{
    if(pGlCreateShaderObjectARB)
        return pGlCreateShaderObjectARB(shaderType);
    return 0;
}

inline void OpenGLExtensionHandler::extGlShaderSourceARB(GLhandleARB shader, int numOfStrings, const char** strings, int* lenOfStrings)
{
    if(pGlShaderSourceARB)
        pGlShaderSourceARB(shader, numOfStrings, strings, lenOfStrings);
}

inline void OpenGLExtensionHandler::extGlCompileShaderARB(GLhandleARB shader)
{
    if(pGlCompileShaderARB)
        pGlCompileShaderARB(shader);
}

inline GLhandleARB OpenGLExtensionHandler::extGlCreateProgramObject(void)
{
    if(pGlCreateProgramObjectARB)
        return pGlCreateProgramObjectARB();
    return 0;
}

inline void OpenGLExtensionHandler::extGlAttachObject(GLhandleARB program, GLhandleARB shader)
{
    if(pGlAttachObjectARB)
        pGlAttachObjectARB(program, shader);
}

inline void OpenGLExtensionHandler::extGlLinkProgramARB(GLhandleARB program)
{
    if(pGlLinkProgramARB)
        pGlLinkProgramARB(program);
}

inline void OpenGLExtensionHandler::extGlUseProgramObject(GLhandleARB prog)
{
    if(pGlUseProgramObjectARB)
        pGlUseProgramObjectARB(prog);
}

inline void OpenGLExtensionHandler::extGlDeleteObject(GLhandleARB object)
{
    if(pGlDeleteObjectARB)
        pGlDeleteObjectARB(object);
}

inline void OpenGLExtensionHandler::extGlGetAttachedObjects(GLhandleARB program, GLsizei maxcount, GLsizei* count, GLhandleARB* shaders)
{
    if(pGlGetAttachedObjectsARB)
        pGlGetAttachedObjectsARB(program, maxcount, count, shaders);
}

inline void OpenGLExtensionHandler::extGlGetInfoLog(GLhandleARB object, GLsizei maxLength, GLsizei* length, GLcharARB* infoLog)
{
    if(pGlGetInfoLogARB)
        pGlGetInfoLogARB(object, maxLength, length, infoLog);
}

inline void OpenGLExtensionHandler::extGlGetObjectParameteriv(GLhandleARB object, GLenum type, GLint* param)
{
    if(pGlGetObjectParameterivARB)
        pGlGetObjectParameterivARB(object, type, param);
}

inline GLint OpenGLExtensionHandler::extGlGetUniformLocationARB(GLhandleARB program, const char* name)
{
    if(pGlGetUniformLocationARB)
        return pGlGetUniformLocationARB(program, name);
    return 0;
}

inline void OpenGLExtensionHandler::extGlUniform4fv(GLint location, GLsizei count, const GLfloat* v)
{
    if(pGlUniform4fvARB)
        pGlUniform4fvARB(location, count, v);
}

inline void OpenGLExtensionHandler::extGlUniform1iv(GLint loc, GLsizei count, const GLint* v)
{
    if(pGlUniform1ivARB)
        pGlUniform1ivARB(loc, count, v);
}

inline void OpenGLExtensionHandler::extGlUniform1fv(GLint loc, GLsizei count, const GLfloat* v)
{
    if(pGlUniform1fvARB)
        pGlUniform1fvARB(loc, count, v);
}

inline void OpenGLExtensionHandler::extGlUniform2fv(GLint loc, GLsizei count, const GLfloat* v)
{
    if(pGlUniform2fvARB)
        pGlUniform2fvARB(loc, count, v);
}

inline void OpenGLExtensionHandler::extGlUniform3fv(GLint loc, GLsizei count, const GLfloat* v)
{
    if(pGlUniform3fvARB)
        pGlUniform3fvARB(loc, count, v);
}

inline void OpenGLExtensionHandler::extGlUniformMatrix2fv(GLint loc, GLsizei count, GLboolean transpose, const GLfloat* v)
{
    if(pGlUniformMatrix2fvARB)
        pGlUniformMatrix2fvARB(loc, count, transpose, v);
}

inline void OpenGLExtensionHandler::extGlUniformMatrix3fv(GLint loc, GLsizei count, GLboolean transpose, const GLfloat* v)
{
    if(pGlUniformMatrix3fvARB)
        pGlUniformMatrix3fvARB(loc, count, transpose, v);
}

inline void OpenGLExtensionHandler::extGlUniformMatrix4fv(GLint loc, GLsizei count, GLboolean transpose, const GLfloat* v)
{
    if(pGlUniformMatrix4fvARB)
        pGlUniformMatrix4fvARB(loc, count, transpose, v);
}

inline void OpenGLExtensionHandler::extGlGetActiveUniformARB(GLhandleARB program,
        GLuint index, GLsizei maxlength, GLsizei* length,
        GLint* size, GLenum* type, GLcharARB* name)
{
    if(pGlGetActiveUniformARB)
        pGlGetActiveUniformARB(program, index, maxlength, length, size, type, name);
}

inline void OpenGLExtensionHandler::extGlPointParameterf(GLint loc, GLfloat f)
{
    if(pGlPointParameterfARB)
        pGlPointParameterfARB(loc, f);
}

inline void OpenGLExtensionHandler::extGlPointParameterfv(GLint loc, const GLfloat* v)
{
    if(pGlPointParameterfvARB)
        pGlPointParameterfvARB(loc, v);
}

inline void OpenGLExtensionHandler::extGlStencilFuncSeparate(GLenum frontfunc, GLenum backfunc, GLint ref, GLuint mask)
{
    if(pGlStencilFuncSeparate)
        pGlStencilFuncSeparate(frontfunc, backfunc, ref, mask);
    else if(pGlStencilFuncSeparateATI)
        pGlStencilFuncSeparateATI(frontfunc, backfunc, ref, mask);
}

inline void OpenGLExtensionHandler::extGlStencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass)
{
    if(pGlStencilOpSeparate)
        pGlStencilOpSeparate(face, fail, zfail, zpass);
    else if(pGlStencilOpSeparateATI)
        pGlStencilOpSeparateATI(face, fail, zfail, zpass);
}

inline void OpenGLExtensionHandler::extGlCompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width,
        GLsizei height, GLint border, GLsizei imageSize, const void* data)
{
    if(pGlCompressedTexImage2D)
        pGlCompressedTexImage2D(target, level, internalformat, width, height, border, imageSize, data);
}

inline void OpenGLExtensionHandler::extGlBindFramebuffer(GLenum target, GLuint framebuffer)
{
    if(pGlBindFramebufferEXT)
        pGlBindFramebufferEXT(target, framebuffer);
}

inline void OpenGLExtensionHandler::extGlDeleteFramebuffers(GLsizei n, const GLuint* framebuffers)
{
    if(pGlDeleteFramebuffersEXT)
        pGlDeleteFramebuffersEXT(n, framebuffers);
}

inline void OpenGLExtensionHandler::extGlGenFramebuffers(GLsizei n, GLuint* framebuffers)
{
    if(pGlGenFramebuffersEXT)
        pGlGenFramebuffersEXT(n, framebuffers);
}

inline GLenum OpenGLExtensionHandler::extGlCheckFramebufferStatus(GLenum target)
{
    if(pGlCheckFramebufferStatusEXT)
        return pGlCheckFramebufferStatusEXT(target);
    else
        return 0;
}

inline void OpenGLExtensionHandler::extGlFramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)
{
    if(pGlFramebufferTexture2DEXT)
        pGlFramebufferTexture2DEXT(target, attachment, textarget, texture, level);
}

inline void OpenGLExtensionHandler::extGlBindRenderbuffer(GLenum target, GLuint renderbuffer)
{
    if(pGlBindRenderbufferEXT)
        pGlBindRenderbufferEXT(target, renderbuffer);
}

inline void OpenGLExtensionHandler::extGlDeleteRenderbuffers(GLsizei n, const GLuint* renderbuffers)
{
    if(pGlDeleteRenderbuffersEXT)
        pGlDeleteRenderbuffersEXT(n, renderbuffers);
}

inline void OpenGLExtensionHandler::extGlGenRenderbuffers(GLsizei n, GLuint* renderbuffers)
{
    if(pGlGenRenderbuffersEXT)
        pGlGenRenderbuffersEXT(n, renderbuffers);
}

inline void OpenGLExtensionHandler::extGlRenderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height)
{
    if(pGlRenderbufferStorageEXT)
        pGlRenderbufferStorageEXT(target, internalformat, width, height);
}

inline void OpenGLExtensionHandler::extGlFramebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer)
{
    if(pGlFramebufferRenderbufferEXT)
        pGlFramebufferRenderbufferEXT(target, attachment, renderbuffertarget, renderbuffer);
}

inline void OpenGLExtensionHandler::extGlActiveStencilFace(GLenum face)
{
    if(pGlActiveStencilFaceEXT)
        pGlActiveStencilFaceEXT(face);
}

inline void OpenGLExtensionHandler::extGlDrawBuffers(GLsizei n, const GLenum* bufs)
{
    if(pGlDrawBuffersARB)
        pGlDrawBuffersARB(n, bufs);
    else if(pGlDrawBuffersATI)
        pGlDrawBuffersATI(n, bufs);
}

inline void OpenGLExtensionHandler::extGlGenBuffers(GLsizei n, GLuint* buffers)
{
    if(pGlGenBuffersARB)
        pGlGenBuffersARB(n, buffers);
}

inline void OpenGLExtensionHandler::extGlBindBuffer(GLenum target, GLuint buffer)
{
    if(pGlBindBufferARB)
        pGlBindBufferARB(target, buffer);
}

inline void OpenGLExtensionHandler::extGlBufferData(GLenum target, GLsizeiptrARB size, const GLvoid* data, GLenum usage)
{
    if(pGlBufferDataARB)
        pGlBufferDataARB(target, size, data, usage);
}

inline void OpenGLExtensionHandler::extGlDeleteBuffers(GLsizei n, const GLuint* buffers)
{
    if(pGlDeleteBuffersARB)
        pGlDeleteBuffersARB(n, buffers);
}

inline void OpenGLExtensionHandler::extGlBufferSubData(GLenum target, GLintptrARB offset, GLsizeiptrARB size, const GLvoid* data)
{
    if(pGlBufferSubDataARB)
        pGlBufferSubDataARB(target, offset, size, data);
}

inline void OpenGLExtensionHandler::extGlGetBufferSubData(GLenum target, GLintptrARB offset, GLsizeiptrARB size, GLvoid* data)
{
    if(pGlGetBufferSubDataARB)
        pGlGetBufferSubDataARB(target, offset, size, data);
}

inline void* OpenGLExtensionHandler::extGlMapBuffer(GLenum target, GLenum access)
{
    if(pGlMapBufferARB)
        return pGlMapBufferARB(target, access);
    return 0;
}

inline GLboolean OpenGLExtensionHandler::extGlUnmapBuffer(GLenum target)
{
    if(pGlUnmapBufferARB)
        return pGlUnmapBufferARB(target);
    return false;
}

inline GLboolean OpenGLExtensionHandler::extGlIsBuffer(GLuint buffer)
{
    if(pGlIsBufferARB)
        return pGlIsBufferARB(buffer);
    return false;
}

inline void OpenGLExtensionHandler::extGlGetBufferParameteriv(GLenum target, GLenum pname, GLint* params)
{
    if(pGlGetBufferParameterivARB)
        pGlGetBufferParameterivARB(target, pname, params);
}

inline void OpenGLExtensionHandler::extGlGetBufferPointerv(GLenum target, GLenum pname, GLvoid** params)
{
    if(pGlGetBufferPointervARB)
        pGlGetBufferPointervARB(target, pname, params);
}

inline void OpenGLExtensionHandler::extGlProvokingVertex(GLenum mode)
{
    if(mFeatureAvailable[LYNX_ARB_provoking_vertex] && pGlProvokingVertexARB)
        pGlProvokingVertexARB(mode);
    else if(mFeatureAvailable[LYNX_EXT_provoking_vertex] && pGlProvokingVertexEXT)
        pGlProvokingVertexEXT(mode);
}

inline void OpenGLExtensionHandler::extGlColorMaskIndexed(GLuint buf, GLboolean r, GLboolean g, GLboolean b, GLboolean a)
{
    if(mFeatureAvailable[LYNX_EXT_draw_buffers2] && pGlColorMaskIndexedEXT)
        pGlColorMaskIndexedEXT(buf, r, g, b, a);
}

inline void OpenGLExtensionHandler::extGlEnableIndexed(GLenum target, GLuint index)
{
    if(mFeatureAvailable[LYNX_EXT_draw_buffers2] && pGlEnableIndexedEXT)
        pGlEnableIndexedEXT(target, index);
}

inline void OpenGLExtensionHandler::extGlDisableIndexed(GLenum target, GLuint index)
{
    if(mFeatureAvailable[LYNX_EXT_draw_buffers2] && pGlDisableIndexedEXT)
        pGlDisableIndexedEXT(target, index);
}

inline void OpenGLExtensionHandler::extGlBlendFuncIndexed(GLuint buf, GLenum src, GLenum dst)
{
    if(mFeatureAvailable[LYNX_ARB_draw_buffers_blend] && pGlBlendFunciARB)
        pGlBlendFunciARB(buf, src, dst);
    if(mFeatureAvailable[LYNX_AMD_draw_buffers_blend] && pGlBlendFuncIndexedAMD)
        pGlBlendFuncIndexedAMD(buf, src, dst);
}

inline void OpenGLExtensionHandler::extGlProgramParameteri(GLuint program, GLenum pname, GLint value)
{
    if(query_feature(EVMF_GEOMETRY_SHADER))
    {
        if(pGlProgramParameteriARB)
            pGlProgramParameteriARB(program, pname, value);
        else if(pGlProgramParameteriEXT)
            pGlProgramParameteriEXT(program, pname, value);
    }
}

} // namespace Lynx

#endif // __LYNX_EXTENSION_HANDLER_HPP_INCLUDED__

